//
//  UPDeviceInfo.m
//  Uang Pasti
//
//  Created by 李永彬 on 2025/8/28.
//

#import "UPDeviceInfo.h"
#import <sys/utsname.h>

@implementation UPDeviceInfo

+ (nullable NSDictionary<NSString *, NSNumber *> *)getStorage {
    NSArray<NSString *> *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths firstObject];
    
    if (!documentsDirectory) {
        return nil;
    }
    
    NSError *error = nil;
    NSDictionary<NSFileAttributeKey, id> *attributes = [[NSFileManager defaultManager] attributesOfFileSystemForPath:documentsDirectory error:&error];
    
    if (error) {
        NSLog(@"Error: %@", error.localizedDescription);
        return nil;
    }
    
    NSNumber *totalSize = attributes[NSFileSystemSize];
    NSNumber *freeSize = attributes[NSFileSystemFreeSize];
    
    if (!totalSize || !freeSize) {
        return nil;
    }
    
    return @{
        @"total": totalSize,
        @"free": freeSize
    };
}

+ (NSDictionary<NSString *, NSNumber *> *)getSystemMemory {
    uint64_t totalMemory = [NSProcessInfo processInfo].physicalMemory;
    
    mach_port_t host_port = mach_host_self();
    mach_msg_type_number_t host_size = HOST_VM_INFO64_COUNT;
    vm_size_t page_size;
    vm_statistics64_data_t vm_stat;
    kern_return_t ret;
    
    ret = host_page_size(host_port, &page_size);
    if (ret != KERN_SUCCESS) {
        NSLog(@"获取页面大小失败: %d", ret);
        return @{@"free": @0, @"total": @(totalMemory)};
    }
    
    ret = host_statistics64(host_port, HOST_VM_INFO64, (host_info64_t)&vm_stat, &host_size);
    if (ret != KERN_SUCCESS) {
        NSLog(@"获取内存信息失败: %d", ret);
        return @{@"free": @0, @"total": @(totalMemory)};
    }
    
    uint64_t freeMemory = (vm_stat.free_count + vm_stat.inactive_count) * page_size;
    
    return @{
        @"free": @(freeMemory),
        @"total": @(totalMemory)
    };
}

+ (NSDictionary<NSString *, id> *)getBatteryInfo {
    UIDevice *device = [UIDevice currentDevice];
    [device setBatteryMonitoringEnabled:YES];
    
    float batteryLevel = device.batteryLevel;
    
    BOOL isCharging = NO;
    switch (device.batteryState) {
        case UIDeviceBatteryStateCharging:
        case UIDeviceBatteryStateFull:
            isCharging = YES;
            break;
        case UIDeviceBatteryStateUnplugged:
            isCharging = NO;
            break;
        case UIDeviceBatteryStateUnknown:
        default:
            isCharging = NO;
            break;
    }
    
    [device setBatteryMonitoringEnabled:NO];
    
    return @{
        @"level": @(batteryLevel),
        @"isCharging": @(isCharging)
    };
}

+ (NSString *)systemVersion {
    return [UIDevice currentDevice].systemVersion;
}

+ (NSString *)modelCode {
    struct utsname systemInfo;
    uname(&systemInfo);
    return [NSString stringWithCString:systemInfo.machine encoding:NSUTF8StringEncoding];
}

+ (nullable NSDictionary<NSString *, id> *)getDeviceInfo {
    NSDictionary<NSString *, NSDictionary<NSString *, id> *> *screenSizeMap = @{
        // iPhone 第一代
        @"iPhone1,1": @{@"name": @"iPhone", @"measure": @3.5},
        
        // iPhone 3G/3GS
        @"iPhone1,2": @{@"name": @"iPhone 3G", @"measure": @3.5},
        @"iPhone2,1": @{@"name": @"iPhone 3GS", @"measure": @3.5},
        
        // iPhone 4/4S
        @"iPhone3,1": @{@"name": @"iPhone 4", @"measure": @3.5},
        @"iPhone3,2": @{@"name": @"iPhone 4", @"measure": @3.5},
        @"iPhone3,3": @{@"name": @"iPhone 4", @"measure": @3.5},
        @"iPhone4,1": @{@"name": @"iPhone 4S", @"measure": @3.5},
        
        // iPhone 5/5C/5S
        @"iPhone5,1": @{@"name": @"iPhone 5", @"measure": @4.0},
        @"iPhone5,2": @{@"name": @"iPhone 5", @"measure": @4.0},
        @"iPhone5,3": @{@"name": @"iPhone 5C", @"measure": @4.0},
        @"iPhone5,4": @{@"name": @"iPhone 5C", @"measure": @4.0},
        @"iPhone6,1": @{@"name": @"iPhone 5S", @"measure": @4.0},
        @"iPhone6,2": @{@"name": @"iPhone 5S", @"measure": @4.0},
        
        // iPhone 6/6 Plus
        @"iPhone7,1": @{@"name": @"iPhone 6 Plus", @"measure": @5.5},
        @"iPhone7,2": @{@"name": @"iPhone 6", @"measure": @4.7},
        @"iPhone8,1": @{@"name": @"iPhone 6S", @"measure": @4.7},
        @"iPhone8,2": @{@"name": @"iPhone 6S Plus", @"measure": @5.5},
        @"iPhone8,4": @{@"name": @"iPhone SE (1st)", @"measure": @4.0},
        
        // iPhone 7/8
        @"iPhone9,1": @{@"name": @"iPhone 7", @"measure": @4.7},
        @"iPhone9,2": @{@"name": @"iPhone 7 Plus", @"measure": @5.5},
        @"iPhone9,3": @{@"name": @"iPhone 7", @"measure": @4.7},
        @"iPhone9,4": @{@"name": @"iPhone 7 Plus", @"measure": @5.5},
        @"iPhone10,1": @{@"name": @"iPhone 8", @"measure": @4.7},
        @"iPhone10,2": @{@"name": @"iPhone 8 Plus", @"measure": @5.5},
        @"iPhone10,4": @{@"name": @"iPhone 8", @"measure": @4.7},
        @"iPhone10,5": @{@"name": @"iPhone 8 Plus", @"measure": @5.5},
        
        // iPhone X/XS/XR/11
        @"iPhone10,3": @{@"name": @"iPhone X", @"measure": @5.8},
        @"iPhone10,6": @{@"name": @"iPhone X", @"measure": @5.8},
        @"iPhone11,2": @{@"name": @"iPhone XS", @"measure": @5.8},
        @"iPhone11,4": @{@"name": @"iPhone XS Max", @"measure": @6.5},
        @"iPhone11,6": @{@"name": @"iPhone XS Max", @"measure": @6.5},
        @"iPhone11,8": @{@"name": @"iPhone XR", @"measure": @6.1},
        @"iPhone12,1": @{@"name": @"iPhone 11", @"measure": @6.1},
        @"iPhone12,3": @{@"name": @"iPhone 11 Pro", @"measure": @5.8},
        @"iPhone12,5": @{@"name": @"iPhone 11 Pro Max", @"measure": @6.5},
        
        // iPhone 12 系列
        @"iPhone13,1": @{@"name": @"iPhone 12 mini", @"measure": @5.4},
        @"iPhone13,2": @{@"name": @"iPhone 12", @"measure": @6.1},
        @"iPhone13,3": @{@"name": @"iPhone 12 Pro", @"measure": @6.1},
        @"iPhone13,4": @{@"name": @"iPhone 12 Pro Max", @"measure": @6.7},
        
        // iPhone 13 系列
        @"iPhone14,4": @{@"name": @"iPhone 13 mini", @"measure": @5.4},
        @"iPhone14,5": @{@"name": @"iPhone 13", @"measure": @6.1},
        @"iPhone14,2": @{@"name": @"iPhone 13 Pro", @"measure": @6.1},
        @"iPhone14,3": @{@"name": @"iPhone 13 Pro Max", @"measure": @6.7},
        
        // iPhone 14 系列
        @"iPhone14,6": @{@"name": @"iPhone SE (3rd)", @"measure": @4.7},
        @"iPhone14,7": @{@"name": @"iPhone 14", @"measure": @6.1},
        @"iPhone14,8": @{@"name": @"iPhone 14 Plus", @"measure": @6.7},
        @"iPhone15,2": @{@"name": @"iPhone 14 Pro", @"measure": @6.1},
        @"iPhone15,3": @{@"name": @"iPhone 14 Pro Max", @"measure": @6.7},
        
        // iPhone 15 系列
        @"iPhone15,4": @{@"name": @"iPhone 15", @"measure": @6.1},
        @"iPhone15,5": @{@"name": @"iPhone 15 Plus", @"measure": @6.7},
        @"iPhone16,1": @{@"name": @"iPhone 15 Pro", @"measure": @6.1},
        @"iPhone16,2": @{@"name": @"iPhone 15 Pro Max", @"measure": @6.7}
    };
    
    NSString *modelCode = [self modelCode];
    return screenSizeMap[modelCode];
}

+ (NSInteger)isSimulator {
#if TARGET_OS_SIMULATOR
    return 1;
#else
    return 0;
#endif
}

+ (NSInteger)isJailbroken {
    NSArray<NSString *> *jailbreakPaths = @[
        @"/Applications/Cydia.app",
        @"/Library/MobileSubstrate/MobileSubstrate.dylib",
        @"/bin/bash",
        @"/usr/sbin/sshd",
        @"/etc/apt",
        @"/private/var/lib/apt/"
    ];
    
    for (NSString *path in jailbreakPaths) {
        if ([[NSFileManager defaultManager] fileExistsAtPath:path]) {
            return 1;
        }
    }
    
    NSString *testString = @"Jailbreak Test";
    NSError *error = nil;
    BOOL success = [testString writeToFile:@"/private/JailbreakTest.txt" atomically:YES encoding:NSUTF8StringEncoding error:&error];
    
    if (success) {
        [[NSFileManager defaultManager] removeItemAtPath:@"/private/JailbreakTest.txt" error:nil];
        return 1;
    }
    
    return 0;
}

+ (NSString *)timezoneID {
    NSInteger secondsFromGMT = [[NSTimeZone localTimeZone] secondsFromGMT];
    NSInteger hours = secondsFromGMT / 3600;
    return [NSString stringWithFormat:@"GMT%+ld", (long)hours];
}

+ (NSInteger)isUsingProxy {
    CFDictionaryRef proxySettings = CFNetworkCopySystemProxySettings();
    NSDictionary *dict = (__bridge NSDictionary *)proxySettings;
    
    if (dict) {
        NSString *httpProxy = dict[@"HTTPProxy"];
        if (httpProxy && [httpProxy length] > 0) {
            CFRelease(proxySettings);
            return 1;
        }
        CFRelease(proxySettings);
    }
    
    return 0;
}

+ (NSInteger)isUsingVPN {
    NSArray<NSString *> *vpnInterfaces = @[@"utun", @"tun", @"ppp", @"ipsec"];
    struct ifaddrs *interfaces = NULL;
    struct ifaddrs *temp_addr = NULL;
    int success = 0;
    
    success = getifaddrs(&interfaces);
    if (success == 0) {
        temp_addr = interfaces;
        while (temp_addr != NULL) {
            NSString *interfaceName = [NSString stringWithUTF8String:temp_addr->ifa_name];
            for (NSString *vpnInterface in vpnInterfaces) {
                if ([interfaceName hasPrefix:vpnInterface]) {
                    freeifaddrs(interfaces);
                    return 1;
                }
            }
            temp_addr = temp_addr->ifa_next;
        }
    }
    freeifaddrs(interfaces);
    return 0;
}

+ (NSString *)carrierName {
    CTTelephonyNetworkInfo *networkInfo = [[CTTelephonyNetworkInfo alloc] init];
    
    if (@available(iOS 12.0, *)) {
        NSDictionary<NSString *, CTCarrier *> *carriers = networkInfo.serviceSubscriberCellularProviders;
        if (carriers.count > 0) {
            CTCarrier *carrier = carriers.allValues.firstObject;
            return carrier.carrierName ?: @"Unknown";
        }
    } else {
        CTCarrier *carrier = networkInfo.subscriberCellularProvider;
        return carrier.carrierName ?: @"Unknown";
    }
    
    return @"Unknown";
}

+ (NSString *)deviceLanguage {
    NSArray<NSString *> *preferredLanguages = [NSLocale preferredLanguages];
    NSString *language = [preferredLanguages firstObject];
    if (language) {
        NSArray<NSString *> *components = [language componentsSeparatedByString:@"-"];
        return [components firstObject] ?: @"en";
    }
    return @"en";
}

+ (NSString *)networkType {
    SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithName(NULL, "www.apple.com");
    SCNetworkReachabilityFlags flags;
    BOOL success = SCNetworkReachabilityGetFlags(reachability, &flags);
    CFRelease(reachability);
    
    if (!success) {
        return @"Unknown Network";
    }
    
    if (flags & kSCNetworkReachabilityFlagsIsWWAN) {
        return @"4G";
    } else if (flags & kSCNetworkReachabilityFlagsReachable) {
        return @"WIFI";
    } else {
        return @"Bad Network";
    }
}

+ (NSInteger)isPhone {
    return [[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone ? 1 : 0;
}

+ (NSString *)ipAddress {
    NSString *address = @"Unknown";
    struct ifaddrs *interfaces = NULL;
    struct ifaddrs *temp_addr = NULL;
    int success = 0;
    
    success = getifaddrs(&interfaces);
    if (success == 0) {
        temp_addr = interfaces;
        while (temp_addr != NULL) {
            if (temp_addr->ifa_addr->sa_family == AF_INET) {
                NSString *interfaceName = [NSString stringWithUTF8String:temp_addr->ifa_name];
                if ([interfaceName isEqualToString:@"en0"]) {
                    char hostname[NI_MAXHOST];
                    getnameinfo(temp_addr->ifa_addr, sizeof(struct sockaddr_in), hostname, NI_MAXHOST, NULL, 0, NI_NUMERICHOST);
                    address = [NSString stringWithUTF8String:hostname];
                }
            }
            temp_addr = temp_addr->ifa_next;
        }
    }
    freeifaddrs(interfaces);
    return address;
}

+ (NSString *)macAddress {
    NSArray<NSString *> *interfaceNames = (__bridge_transfer NSArray<NSString *> *)CNCopySupportedInterfaces();
    
    for (NSString *interfaceName in interfaceNames) {
        NSDictionary<NSString *, id> *networkInfo = (__bridge_transfer NSDictionary<NSString *, id> *)CNCopyCurrentNetworkInfo((__bridge CFStringRef)interfaceName);
        if (networkInfo) {
            NSString *bssid = networkInfo[@"BSSID"];
            if (bssid) {
                return bssid;
            }
        }
    }
    
    return @"Unknown";
}

@end
